package com.feixiang.springbootinit.processor;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.feixiang.springbootinit.common.ErrorCode;
import com.feixiang.springbootinit.constant.WxConstant;
import com.feixiang.springbootinit.exception.BusinessException;
import com.feixiang.springbootinit.model.entity.wechat.ChatData;
import com.feixiang.springbootinit.model.entity.wechat.QwMessage;
import com.feixiang.springbootinit.model.enums.SessionArchiveMsgActionEnum;
import com.feixiang.springbootinit.model.enums.SessionArchiveMsgTypeEnum;
import com.feixiang.springbootinit.model.vo.wechat.MsgVO;
import com.feixiang.springbootinit.service.QwMessageService;
import com.feixiang.springbootinit.strategy.MessageProcessingStrategy;
import com.feixiang.springbootinit.strategy.MessageStrategyFactory;
import com.feixiang.springbootinit.utils.SessionArchiveUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@Slf4j
//@Component
/**
 * 存在问题 todo
 * 太消耗数据库
 *
 */
@Deprecated
public class SessionArchiveProcessor {
    // 线程池配置
    private static final int IO_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; // IO密集型任务
    private static final int CPU_POOL_SIZE = Runtime.getRuntime().availableProcessors(); // CPU密集型任务
    private ExecutorService ioExecutor;
    private ExecutorService cpuExecutor;

    // SDK实例（使用AtomicLong确保原子性）
    private static final AtomicLong sdkInstance = new AtomicLong(0);
    private static PrivateKey privateKey;
    private static final Object initLock = new Object();

    @Autowired
    private TransactionTemplate transactionTemplate; // 注入事务模板

    /**
     * 获取全局SDK实例（线程安全）
     */
    public static long getGlobalSdkInstance() {
        long instance = sdkInstance.get();
        if (instance == 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "企微会话存档SDK未初始化");
        }
        return instance;
    }

    @Autowired
    private QwMessageService messageService;

    @Autowired
    private MessageStrategyFactory messageStrategyFactory;

    @PostConstruct
    public void init() {
        // 初始化线程池，使用更合理的配置
        ioExecutor = new ThreadPoolExecutor(
                IO_POOL_SIZE,
                IO_POOL_SIZE,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000),
                new NamedThreadFactory("wx-io-pool"),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        cpuExecutor = new ThreadPoolExecutor(
                CPU_POOL_SIZE,
                CPU_POOL_SIZE,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000),
                new NamedThreadFactory("wx-cpu-pool"),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        // 确保SDK只被初始化一次
        if (sdkInstance.get() == 0) {
            synchronized (initLock) {
                if (sdkInstance.get() == 0) {
                    try {
                        long instance = SessionArchiveUtil.initSDK(WxConstant.CORP_ID, WxConstant.SECRET_KEY);
                        sdkInstance.set(instance);
                        privateKey = SessionArchiveUtil.getPrivateKey(WxConstant.PRIVKEY);
                        if (privateKey == null) {
                            sdkInstance.set(0);
                            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "企微解密私钥初始化失败");
                        }
                        log.info("SessionArchiveProcessor初始化成功，SDK实例: {}", instance);
                    } catch (Exception e) {
                        log.error("SessionArchiveProcessor初始化失败", e);
                        sdkInstance.set(0);
                        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "会话存档处理器初始化失败");
                    }
                }
            }
        }
    }

    @PreDestroy
    public void destroy() {
        // 关闭线程池
        shutdownExecutor(ioExecutor, "IO线程池");
        shutdownExecutor(cpuExecutor, "CPU线程池");

        // 释放SDK资源
        long instance = sdkInstance.getAndSet(0);
        if (instance != 0) {
            SessionArchiveUtil.destroy();
            log.info("SessionArchiveProcessor资源已释放");
        }
    }

    public List<QwMessage> processMessages(List<ChatData> chatDataList) {
        if (chatDataList == null || chatDataList.isEmpty()) {
            return Collections.emptyList();
        }
        // 检查是否已处理
//        if (messageService.existsByMsgId(chatData.getMsgId())) {
//            log.info("消息已处理，跳过: {}", msgVO.getMsgid());
//            return null;
//        }
        List<CompletableFuture<QwMessage>> futures = new ArrayList<>(chatDataList.size());
        /**
         * 线程池会为每个任务分配线程，但同一个 ChatData 只会被一个任务链处理
         */
        for (ChatData chatData : chatDataList) {
            CompletableFuture<QwMessage> future = CompletableFuture
                    .supplyAsync(() -> decryptMessage(chatData), ioExecutor)
                    .thenApplyAsync(msgVO -> processMessage(msgVO, chatData), cpuExecutor);

            futures.add(future);
        }

        // 合并结果
        List<QwMessage> results = new ArrayList<>(chatDataList.size());
        for (CompletableFuture<QwMessage> future : futures) {
            try {
                QwMessage message = future.get(300, TimeUnit.SECONDS);
                if (message != null) {
                    results.add(message);
                }
            } catch (TimeoutException e) {
                log.error("消息处理超时，seq: {}", chatDataList.get(futures.indexOf(future)).getSeq(), e);
            } catch (Exception e) {
                log.error("处理消息异常", e);
            }
        }

        return results;
    }

    private MsgVO decryptMessage(ChatData chatData) {
        try {
            String randomKey = SessionArchiveUtil.decrptyRandomKey(privateKey, chatData.getEncryptRandomKey());
            // 使用原子方式获取SDK实例
            String decryptMsg = SessionArchiveUtil.decryptData(sdkInstance.get(), randomKey, chatData.getEncryptChatMsg());
            return JSONUtil.toBean(decryptMsg, MsgVO.class);
        } catch (Exception e) {
            log.error("消息解密失败, seq: {}", chatData.getSeq(), e);
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "消息解密失败");
        }
    }
    //todo 多线程情况下，考虑加锁，分布式锁或者本地锁
    private QwMessage processMessage(MsgVO msgVO, ChatData chatData) {
        // 使用编程式事务，确保操作原子性
        return transactionTemplate.execute(status -> {
            try {
                // 1. 构建并保存基础消息
                QwMessage message = buildBaseMessage(chatData, msgVO, JSONUtil.toJsonStr(msgVO));
                messageService.save(message);
                // 2. 调用策略处理（如图片/文件/视频/语音消息）
                MessageProcessingStrategy processor = messageStrategyFactory.getStrategy(
                        SessionArchiveMsgTypeEnum.fromString(msgVO.getMsgtype()));
                if (processor != null) {
                    processor.process(msgVO, message); // 策略中的数据库操作会加入当前事务
                }

                return message;
            } catch (Exception e) {
                // 发生异常时，手动标记事务回滚
                status.setRollbackOnly();
                log.error("消息处理失败, seq: {}", chatData.getSeq(), e);
                return null;
            }
        });
    }

    private void shutdownExecutor(ExecutorService executor, String poolName) {
        try {
            executor.shutdown();
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
                log.warn("{}强制关闭", poolName);
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    private QwMessage buildBaseMessage(ChatData chatData, MsgVO msgVO, String decryptMsg) {
        // 1. 参数校验
        if (chatData.getSeq() == null || StringUtils.isAnyBlank(msgVO.getMsgid(), msgVO.getAction(), decryptMsg)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数缺失: chatData.seq, msgVO.msgid, msgVO.action, decryptMsg 不能为空");
        }
        // 2. 初始化基础对象
        QwMessage message = new QwMessage();
        message.setSeq(chatData.getSeq());
        message.setMsgId(msgVO.getMsgid());
        message.setAction(msgVO.getAction());
        message.setContent(decryptMsg);
        // 3. 根据action类型处理不同分支
        String action = msgVO.getAction();
        if (SessionArchiveMsgActionEnum.SWITCH.getCode().equals(action)) {
            handleSwitchMessage(message, msgVO);
        } else if (SessionArchiveMsgActionEnum.SEND.getCode().equals(action)) {
            handleSendMessage(message, msgVO);
        } else if (SessionArchiveMsgActionEnum.RECALL.getCode().equals(action)) {
            handleSendMessage(message, msgVO); // RECALL和SEND处理逻辑相同
        } else {
            log.warn("未知的action类型: {}", action);
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "非法的action类型: " + action);
        }

        return message;
    }

    // 处理切换企业日志
    private void handleSwitchMessage(QwMessage message, MsgVO msgVO) {
        message.setMsgtime(DateUtil.date(msgVO.getTime()));
        message.setMsgtype(SessionArchiveMsgActionEnum.SWITCH.getCode());
        log.debug("构建企业切换消息: msgId={}", msgVO.getMsgid());
    }

    // 处理发送/撤回消息(SEND和RECALL共用)
    private void handleSendMessage(QwMessage message, MsgVO msgVO) {
        message.setFromId(msgVO.getFrom());
        message.setMsgtype(msgVO.getMsgtype());
        message.setTolist(JSONUtil.toJsonStr(msgVO.getTolist()));
        message.setRoomid(msgVO.getRoomid());
        Date msgTime = DateUtil.date(msgVO.getMsgtime());
        message.setMsgtime(msgTime);
        message.setCreatedTime(new Date());
        log.debug("构建{}消息: msgId={}, 发送时间={}",
                message.getAction(), message.getMsgId(), msgTime);
    }
}

/**
 * 线程工厂
 */
class NamedThreadFactory implements ThreadFactory {
    private static final Logger log = LoggerFactory.getLogger(NamedThreadFactory.class);
    private final String namePrefix;
    private final AtomicInteger threadNumber = new AtomicInteger(1);

    NamedThreadFactory(String namePrefix) {
        this.namePrefix = namePrefix;
    }

    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r, namePrefix + "-" + threadNumber.getAndIncrement());
        log.info("创建线程: {}", thread.getName());
        return thread;
    }
}